package com.service.other;

import java.io.File;
import java.util.Date;
import java.util.List;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;

import com.service.bean.other.VehicleScalar;
import com.service.bean.signal.GpsSignal;
import com.service.cache.CacheManager;
import com.service.calculate.vehicle.ProcessPool;
import com.service.scheduler.listener.BaseListener;
import com.service.scheduler.listener.SaveGpsListener;
import com.service.scheduler.listener.SaveWorkChangeListener;
import com.service.scheduler.listener.SaveWorkSpeedListener;
import com.service.scheduler.sched.SaveGpsSched;
import com.service.scheduler.sched.SaveWorkChangeSched;
import com.service.scheduler.sched.SaveWorkSpeedSched;
import com.service.scheduler.server.SchedulerServer;
import com.service.socket.server.VehicleServer;
import com.service.tools.DateFormat;
import com.service.tools.JsonConvert;

/**
 * Java程序关闭时的处理方法</br>
 * 主要目的是在退出前将缓存中计算后的变化量保存到指定文件中
 * 以及立即启动存储Job
 * @author wt
 *
 */
public class ServerClose {
	
	public static void close() {
		try {
			System.out.println("服务器开始关闭...");
			
			//step1:关闭netty服务
			step1();
			hangderOilAbnormal();
			//step2:等待信号计算结束
			step2();
			//step3:Job立即执行，并等待Job执行结束
			step3();
			//step4:存储前后两条GPS数据计算的中间标识结果
			step4();			
			//stepEnd:倒计时
			stepEnd();
			
		} catch (Exception e) {
			Logger.err(e);
		}
	}

	/**
	 * 关闭Netty服务
	 */
	public static void step1() {	
		System.out.println("step1：netty is closing");

		//关闭Netty服务
		VehicleServer.instance().stop();

		System.out.println("step1：netty is closed");
	}
	
	/**
	 * 等待信号计算结束
	 */	
	public static void step2() {	
		System.out.println("step2：scalarCal is closing");
		while(true){
			boolean bReturn = true;
			for(VehicleScalar vehicleScalar:CacheManager.instance().scalarCalers.values()){
				if (vehicleScalar.ScalarCalThread != null && vehicleScalar.ScalarCalThread.isAlive()) {
					bReturn = false;
					break;
				}
			}
			if (bReturn){
				break;
			}
		}
		System.out.println("step2：scalarCal is closed");
	}
	
	/**
	 * Job立即执行，并等待Job执行结束
	 */	
	public static void step3() {	
		System.out.println("step3：job is closing");
		
		runJob(SaveGpsSched.class.getSimpleName(),"saveGps","com.service.cache",new SaveGpsListener());
		runJob(SaveWorkChangeSched.class.getSimpleName(),"saveWorkChange","com.service.cache",new SaveWorkChangeListener());
		runJob(SaveWorkSpeedSched.class.getSimpleName(),"saveWorkSpeed","com.service.cache",new SaveWorkSpeedListener());
	
		SchedulerServer.instance().shutdown();
		System.out.println("step3：job is closed");
	}	
	
	/**
	 * 存储前后两条GPS数据计算的中间标识结果
	 */	
	public static void step4() {
		System.out.println("step4：variableMap is closing");

		if (!CacheManager.instance().variableMap.isEmpty()) {
			JsonConvert jc = new JsonConvert();
			String json = jc.object2Json(CacheManager.instance().variableMap);			
			String hookSavePath = ServerConfig.instance().hook_savepath + File.separator + DateFormat.format(new Date(), "yyyyMMdd") + ".txt";
			Writer.append(hookSavePath, json);
		}
		System.out.println("step4：variableMap is closed");	
	}	
	
	/**
	 * 存储前后两条GPS数据计算的中间标识结果
	 */	
	public static void stepEnd() {

		long startTime = System.currentTimeMillis();
		long closeTime = System.currentTimeMillis()+1000*5;
		int i = 0;
		while(System.currentTimeMillis()<=closeTime){
			if ((System.currentTimeMillis()-startTime)>=1000*i && i++>0){
				System.out.println("画面关闭倒计时 "+(closeTime-System.currentTimeMillis())/1000+"s");
			}			
		}
	}	
	
	/**
	 * 立即启动Job，并等待Job运行结束
	 */	
	public static void runJob(String schedName, String jobName,
			String groupName,BaseListener jobListener) {
		boolean bAdd = false;
		boolean bStart = false;
		
		
		Scheduler sched = CacheManager.instance().schedMap.get(schedName);
		try {
			//Scheduler未启动的场合,不处理
			if (sched == null || !sched.isStarted()){
				return;
			}
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			Logger.err(e);
		}
		
		bAdd = SchedulerServer.instance().addListen(schedName,jobName,groupName,jobListener);
		bStart = SchedulerServer.instance().triggerJob(schedName, jobName, groupName);
		
		while(bAdd && bStart && !jobListener.isExecutedFlag() ){
			//waiting
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 处理缓存中的异常油位，以免数据丢失
	 */
	private static void hangderOilAbnormal() {
		for (String equipmentId : CacheManager.instance().oilNormal.keySet()) {
			List<GpsSignal> listAbnormal = CacheManager.instance().oilAbnormal.get(equipmentId);
			if (listAbnormal != null) {
				GpsSignal signal = CacheManager.instance().oilNormal.get(equipmentId);
				VehicleScalar vehicleScalar = CacheManager.instance().scalarCalers.get(signal.gpsNo);
				for (int i = 0; i < listAbnormal.size(); i++) {
					GpsSignal s = listAbnormal.get(i);
					s.oilHeight = signal.oilHeight;
					CacheManager.instance().getSignalQueue(signal.gpsNo).offer(s);
				}
				ProcessPool.scalarCal(vehicleScalar, signal.gpsNo);
			}
		}
	}
}
